package edu.tsinghua.mrpvc.device.tv;

import java.util.Calendar;
import java.util.Hashtable;
import java.util.Map;
import java.util.Random;

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventHandler;
import org.osgi.util.tracker.ServiceTracker;

import edu.tsinghua.mrpvc.device.RFIDDetect;
import edu.tsinghua.mrpvc.device.TvDevice;

public class TvDeviceImpl implements TvDevice, EventHandler{

	private String playState;
	private int powerState;
	private int channel;
	private int volume;
	private String ID;
	private ServiceTracker tracker;
	private BundleContext context;
	private float playTime;
	
	public TvDeviceImpl(BundleContext context, String ID){
		this.context = context;
		this.ID = new String(ID);
		tracker = new ServiceTracker(context, EventAdmin.class.getName(), null);
		tracker.open();		
		channel = 0;
		volume = 0;
		playState = TvDevice.Constants.STATE_SLEEP;
		powerState = 0;	
		playTime = 0;
	}
	
	private void generEvent(){
		EventAdmin eventAdmin = (EventAdmin) tracker.getService();
		if(eventAdmin != null){
			System.out.println(Calendar.getInstance().getTime().toLocaleString() + 
					" Tv: state changed and post event");
			Map<String, String> proper = new Hashtable<String, String>();
			proper.put(TvDevice.EVENT_PROPER_ID, ID);
			proper.put(TvDevice.EVENT_PROPER_POWER_STATE, powerState == 1 ? TvDevice.Constants.POWER_ON : TvDevice.Constants.POWER_OFF);
			proper.put(TvDevice.EVENT_PROPER_CHANNEL, Integer.toString(channel));
			proper.put(TvDevice.EVENT_PROPER_VOLUME, Integer.toString(volume));
			proper.put(TvDevice.EVENT_PROPER_PLAY_TIME, Float.toString(playTime));
			if(playState.equals(TvDevice.Constants.STATE_PLAY)){
				proper.put(TvDevice.EVENT_PROPER_PLAY_STATE, TvDevice.Constants.STATE_PLAY);
			}
			else if(playState.equals(TvDevice.Constants.STATE_SLEEP)){
				proper.put(TvDevice.EVENT_PROPER_PLAY_STATE, TvDevice.Constants.STATE_SLEEP);
			}
			else if(playState.equals(TvDevice.Constants.STATE_PAUSE)){
				proper.put(TvDevice.EVENT_PROPER_PLAY_STATE, TvDevice.Constants.STATE_PAUSE);
			}
			Event event = new Event(TvDevice.EVENT_TOPIC_STATE, proper);
			eventAdmin.postEvent(event);
		}
	}
	@Override
	public int downChannel() {
		// TODO Auto-generated method stub
		channel--;
		System.out.println(Calendar.getInstance().getTime().toLocaleString()+
				" Tv: downChannel executed");
		generEvent();
		return 1;
	}

	@Override
	public int downVolume() {
		// TODO Auto-generated method stub
		volume--;
		System.out.println(Calendar.getInstance().getTime().toLocaleString()+
				" Tv: downVolume executed");
		generEvent();
		return 0;
	}

	@Override
	public String getID() {
		// TODO Auto-generated method stub
		System.out.println(Calendar.getInstance().getTime().toLocaleString()+
				" Tv: getID executed");
		return ID;
	}

	@Override
	public boolean isValid() {
		System.out.println(Calendar.getInstance().getTime().toLocaleString()+
				" Tv: isValid executed");
		return true;
	}

	@Override
	public int play(String url,int appType) {
		// TODO Auto-generated method stub
		System.out.println(Calendar.getInstance().getTime().toLocaleString()+
				" Tv: play executed");
		playState = TvDevice.Constants.STATE_PLAY;
		String type = "" + appType;
		if(type.equals(TvDevice.Constants.MIGRATION_MEDIA_APP)){
			System.out.println(Calendar.getInstance().getTime().toLocaleString()+
					" Tv: play executed;" + "and execute App is migration media player" );
		}
		else if(type.equals(TvDevice.Constants.PICTURE_BROWSE_APP)){
			System.out.println(Calendar.getInstance().getTime().toLocaleString()+
					" Tv: play executed;" + "and execute App is picture browse" );
		}
		else if(type.equals(TvDevice.Constants.GENERAL_MEDIA_APP)){
			System.out.println(Calendar.getInstance().getTime().toLocaleString()+
					" Tv: play executed;" + "and execute App is general media player" );
		}
		generEvent();
		return 1;
	}

	@Override
	public int powerOff() {
		// TODO Auto-generated method stub
		powerState = 0;
		System.out.println(Calendar.getInstance().getTime().toLocaleString()+
				" Tv: Power Off executed");
		playState = TvDevice.Constants.STATE_SLEEP;
		generEvent();
		return 1;
	}

	@Override
	public int powerOn() {
		// TODO Auto-generated method stub
		powerState = 1;
		System.out.println(Calendar.getInstance().getTime().toLocaleString()+
				" Tv: Power On executed");
		playState = TvDevice.Constants.STATE_PLAY;
		generEvent();
		return 1;
	}

	@Override
	public int sleep() {
		// TODO Auto-generated method stub
		playState = TvDevice.Constants.STATE_SLEEP;
		System.out.println(Calendar.getInstance().getTime().toLocaleString()+
				" Tv: sleep executed");
		generEvent();
		return 1;
	}

	@Override
	public int upChannel() {
		// TODO Auto-generated method stub
		channel++;
		System.out.println(Calendar.getInstance().getTime().toLocaleString()+
				" Tv: upChannel executed");
		generEvent();
		return 1;
	}

	@Override
	public int upVolume() {
		// TODO Auto-generated method stub
		volume++;
		System.out.println(Calendar.getInstance().getTime().toLocaleString()+
				" Tv: upVolume executed");
		generEvent();
		return 1;
	}
	@Override
	public int pause() {
		// TODO Auto-generated method stub
		System.out.println(Calendar.getInstance().getTime().toLocaleString()
				+ " Tv: pause exceted");
		playState = TvDevice.Constants.STATE_PAUSE;
		generEvent();
		return 1;
	}
	
	public int openShareFolder(String path){
		System.out.println(Calendar.getInstance().getTime().toLocaleString()
				+ " Tv: open ShareFolder exceted");
		return 1;
	}

	@Override
	public int zoomOut() {
		// TODO Auto-generated method stub
		System.out.println(Calendar.getInstance().getTime().toLocaleString()
				+ " Tv: ZoomOut executed");
		return 1;
	}

	@Override
	public int next() {
		// TODO Auto-generated method stub
		System.out.println(Calendar.getInstance().getTime().toLocaleString()
				+ " Tv: next executed");
		return 1;
	}

	@Override
	public int prev() {
		// TODO Auto-generated method stub
		System.out.println(Calendar.getInstance().getTime().toLocaleString()
				+ " Tv: prev executed");
		return 1;
	}

	@Override
	public int rotate() {
		// TODO Auto-generated method stub'
		System.out.println(Calendar.getInstance().getTime().toLocaleString()
				+ " Tv: rotate executed");
		return 1;
	}

	@Override
	public int zoomIn() {
		// TODO Auto-generated method stub
		System.out.println(Calendar.getInstance().getTime().toLocaleString()
				+ " Tv: ZoomIn executed");
		return 1;
	}

	@Override
	public void handleEvent(Event event) {
		// TODO Auto-generated method stub
		if(event.getTopic().equals(TvDevice.EVENT_TOPIC_ISVALID)){
			if(event.getProperty(TvDevice.EVENT_PROPER_ID) != null && event.getProperty(TvDevice.EVENT_PROPER_ID).equals(ID)){
				generEvent();
			}
		}
		else if(event.getTopic().equals(TvDevice.EVENT_TOPIC_CTRL_MOUSE)){
			if(event.getProperty(TvDevice.EVENT_PROPER_ID) != null && event.getProperty(TvDevice.EVENT_PROPER_ID).equals(ID)){
				System.out.println(Calendar.getInstance().getTime().toLocaleString() +
						" Tv: recieve control mouse event " + event.getProperty(TvDevice.EVENT_PROPER_ACTION) +  " and executed");
			
				if(event.getProperty(TvDevice.EVENT_PROPER_LOCATION_X) != null &&
						event.getProperty(TvDevice.EVENT_PROPER_LOCATION_X).equals("100")){
					ServiceReference ref = context.getServiceReference(RFIDDetect.class.getName());
					RFIDDetect rfid = (RFIDDetect) context.getService(ref);
					System.out.println(Calendar.getInstance().getTime().toLocaleString() + 
							" Tv: control RFID Door System  open");
					rfid.openDoor();
				}
			}
		}
		else if(event.getTopic().equals(TvDevice.EVENT_TOPIC_CTRL_KEY_BOARD)){
			if(event.getProperty(TvDevice.EVENT_PROPER_ID) != null && event.getProperty(TvDevice.EVENT_PROPER_ID).equals(ID)){
				System.out.println(Calendar.getInstance().getTime().toLocaleString() +
						" Tv: recieve control keyBoard event " + event.getProperty(TvDevice.EVENT_PROPER_KEY) +  " and executed");
				
			}
		}
		else if(event.getTopic().equals(TvDevice.EVENT_TOPIC_CTRL)){
			if(event.getProperty(TvDevice.EVENT_PROPER_ID) != null && event.getProperty(TvDevice.EVENT_PROPER_ID).equals(ID)){
				System.out.println(Calendar.getInstance().getTime().toLocaleString() +
						" Tv: recieve control event " + event.getProperty(TvDevice.EVENT_PROPER_ACTION) +  " and executed");
				
				String action = event.getProperty(TvDevice.EVENT_PROPER_ACTION).toString();
				if(action.equals(TvDevice.Constants.ACTION_POWERON)){
					this.powerOn();
				}
				else if(action.equals(TvDevice.Constants.ACTION_POWEROFF)){
					this.powerOff();
				}
				else if(action.equals(TvDevice.Constants.ACTION_DOWNCHANNEL)){
					this.downChannel();
				}
				else if(action.equals(TvDevice.Constants.ACTION_UPCHANNEL)){
					this.upChannel();
				}
				else if(action.equals(TvDevice.Constants.ACTION_UPVOLUME)){
					this.upVolume();
				}
				else if(action.equals(TvDevice.Constants.ACTION_DOWNVOLUME)){
					this.downVolume();
				}
				else if(action.equals(TvDevice.Constants.ACTION_PLAY)){
					int appType = Integer.parseInt((String) (event.getProperty(TvDevice.EVENT_PROPER_APPTYPE)));
					this.play(event.getProperty(TvDevice.EVENT_PROPER_URL).toString(),appType);
				}
				else if(action.equals(TvDevice.Constants.ACTION_SLEEP)){
					this.sleep();
				}
				else if(action.equals(TvDevice.Constants.ACTION_WAKEUP)){
					this.wakeup();
				}
				else if(action.equals(TvDevice.Constants.ACTION_PAUSE)){
					this.pause();
				}
				else if(action.equals(TvDevice.Constants.ACTION_RESUME)){
					this.resume();
				}
				else if(action.equals(TvDevice.Constants.ACTION_STATE_SAVE)){
					this.stateSave();
				}
				else if(action.equals(TvDevice.Constants.ACTION_STATE_RESTORE)){
					
					this.stateRestore(Float.parseFloat((String)event.getProperty(TvDevice.EVENT_PROPER_PLAY_TIME)),
							Integer.parseInt((String)event.getProperty(TvDevice.EVENT_PROPER_VOLUME)));
					this.play(event.getProperty(TvDevice.EVENT_PROPER_URL).toString(), 
							Integer.parseInt((String) event.getProperty(TvDevice.EVENT_PROPER_APPTYPE)));
				}
			}
		}
		
	}


	@Override
	public int stateRestore(float time,int volume) {
		System.out.println(Calendar.getInstance().getTime().toLocaleString()
				+ " Tv: state restore exceted");
		this.volume = volume;
		this.playTime = time;
		return 1;
	}

	@Override
	public int stateSave() {
		System.out.println(Calendar.getInstance().getTime().toLocaleString()
				+ " Tv: state save exceted");
//		volume = 50;
		Random ran = new Random();
		String randomTime = ran.nextInt(5) + "" + ran.nextFloat();
		playTime = ran.nextInt(5) + ran.nextFloat();
		volume = ran.nextInt(50);
		System.out.println("Get the Current Play Time =" + playTime);
		System.out.println("Get the Current Volume =" + volume);
//		playTime = (float) 22.2;
		
		this.generEvent();
		volume = 100;
		playTime = 0;
		return 1;
	}

	@Override
	public int resume() {
		System.out.println(Calendar.getInstance().getTime().toLocaleString()
				+ " Tv: resume exceted");
		playState = TvDevice.Constants.STATE_PLAY;
		generEvent();
		return 1;
	}

	@Override
	public int wakeup() {
		// TODO Auto-generated method stub
		playState = TvDevice.Constants.STATE_PLAY;
		System.out.println(Calendar.getInstance().getTime().toLocaleString()
				+ " Tv: weakup executed");
		generEvent();
		return 1;
	}

}
